package cn.wolfcode.crud.shiro;

import cn.wolfcode.crud.domain.Employee;
import cn.wolfcode.crud.mapper.EmployeeMapper;
import cn.wolfcode.crud.mapper.PermissionMapper;
import cn.wolfcode.crud.mapper.RoleMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component("crmRealm")
public class CrmRealm extends AuthorizingRealm {
    @Autowired
    private  EmployeeMapper employeeMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        super.setCredentialsMatcher(credentialsMatcher);
    }

    //登录
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        //去数据库根据名字去找用户,prin方法就是根据名字
        Employee employee = employeeMapper.selectByName((String) token.getPrincipal());

        //如果不为空就代表有用户
        if(employee!=null){
            //传入账号会和当前的subject绑定,数据的密码,数据的盐(用户名),数据源的名字,指哪个数据源的账户和密码
            return  new SimpleAuthenticationInfo(employee,employee.getPassword(),
                    ByteSource.Util.bytes(employee.getName()),"crmRealm"); //如果不为空带有正确的密码他去判断密码的功能
        }

        return null; //如果返回null,会抛出没有账号异常,
    }


    //授权,提供角色权限信息
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("开始查询---------------");
        //该方法返回哪些角色和权限数据.当前的用户就拥有哪些权限和角色数据
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        //Subject subject = SecurityUtils.getSubject();
         //拿到登录里面传进来的第一个对象
        // Employee employee = (Employee)subject.getPrincipal();

        //形参上已经注入进来绑定好的身份信息了直接去拿就行
        //获取当用户
        Employee employee =(Employee)principals.getPrimaryPrincipal();

        //如果是超级管理员,否则再去查普通用户的权限
        if (employee.isAdmin()) {
            //给他所有的权限和管理角色
            info.addStringPermission("*:*");
            info.addRole("Admin");

        }else {

            //根据员工id查询他拥有的权限
            List<String> permissions = permissionMapper.selectByEmpId(employee.getId());
            //把权限设置给info对象
            info.addStringPermissions(permissions);

            //查询他拥有的角色
            List<String> roles = roleMapper.selectSnByEmpId(employee.getId());
            //把角色设置给info对象
            info.addRoles(roles);
        }
        System.out.println("结束查询---------------");
        return info;
    }
}
